package com.swyc.osschat.Test.shijianlun;

import com.swyc.osschat.Common.Util.JsonUtils;
import io.netty.util.HashedWheelTimer;
import io.netty.util.Timer;
import io.netty.util.concurrent.DefaultThreadFactory;
import lombok.extern.slf4j.Slf4j;
import org.springframework.util.ObjectUtils;

import java.util.Date;
import java.util.concurrent.TimeUnit;

/**
 * @description TODO
 * @Author: z156940l@outlook.com
 * @className NettyDelayQueue
 * @Date: 2023/3/14 15:16
 */
@Slf4j
public class NettyDelayQueue {

    /**
     * 默认的HashedWheelTimer
     * 100毫秒，512个槽位
     */
    public final static Timer HASHED_WHEEL_TIMER = new HashedWheelTimer(
            new DefaultThreadFactory("nettyDelayMsg"),
            100L, TimeUnit.MILLISECONDS, 512, true);

    /**
     * 添加延时任务 - 秒
     * @param timerTask     待处理的任务
     * @param fixDelayTime  延时的时间戳
     * @param <T>
     */
    public static <T> void addDelayTaskWithSeconds(AbstractNettyDelayQueueListener<T> timerTask, long fixDelayTime){
        addDelayTaskWithFixDelayTime(timerTask, fixDelayTime, TimeUnit.SECONDS);
    }

    /**
     * 添加延时任务 - 分
     * @param timerTask     待处理的任务
     * @param fixDelayTime  延时的时间戳
     * @param <T>
     */
    public static <T> void addDelayTaskWithMinutes(AbstractNettyDelayQueueListener<T> timerTask, long fixDelayTime){
        addDelayTaskWithFixDelayTime(timerTask, fixDelayTime, TimeUnit.MILLISECONDS);
    }

    /**
     * 添加延时任务 - 时
     * @param timerTask     待处理的任务
     * @param fixDelayTime  延时的时间戳
     * @param <T>
     */
    public static <T> void addDelayTaskWithHours(AbstractNettyDelayQueueListener<T> timerTask, long fixDelayTime){
        addDelayTaskWithFixDelayTime(timerTask, fixDelayTime, TimeUnit.HOURS);
    }

    /**
     * 添加延时任务-固定的时间以后执行任务
     * @param timerTask     待处理的任务
     * @param fixDelayTime  延时的时间戳
     * @param timeUnit      时间单位
     * @param <T>
     */
    public static <T> void addDelayTaskWithFixDelayTime(AbstractNettyDelayQueueListener<T> timerTask,
                                                        long fixDelayTime,
                                                        TimeUnit timeUnit){
        if (ObjectUtils.isEmpty(timerTask)){
            log.error("timerTask不能为空。");
            return;
        }
        if (fixDelayTime < 0){
            log.error("fixDelayTime不能小于0。");
            return;
        }
        if (timeUnit == null){
            log.error("timeUnit不能为空。");
            return;
        }

        TaskVO<T> taskVO = timerTask.getTaskVO();
        taskVO.setTimestamp(fixDelayTime);
        taskVO.setTimeUnit(timeUnit);
        log.info("添加延迟队列，时间：{}，内容：{}", fixDelayTime, JsonUtils.toJson(taskVO.getData()));
        HASHED_WHEEL_TIMER.newTimeout(timerTask, fixDelayTime, timeUnit);
    }

    /**
     * 添加延时任务 - 未来的某个时间执行任务
     * @param timerTask     待处理的任务
     * @param futureTime    未来的某个时间
     * @param <T>
     */
    public static <T> void addDelayTaskWithFutureTime(AbstractNettyDelayQueueListener<T> timerTask, Date futureTime){
        if (ObjectUtils.isEmpty(timerTask)){
            log.error("timerTask不能为空。");
            return;
        }
        if (futureTime == null || futureTime.getTime() < new Date().getTime()){
            log.error("futureTime不能小于当前时间。");
            return;
        }
        TaskVO<T> taskVO = timerTask.getTaskVO();
        taskVO.setFutureTime(futureTime);
        HASHED_WHEEL_TIMER.newTimeout(timerTask, (futureTime.getTime() - new Date().getTime()), TimeUnit.MILLISECONDS);
    }
}
